﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Web;
using System.Security.Cryptography;
using System.IO;


namespace urlwatcher
{
    public class TokenUtils
    {
        static ASCIIEncoding textConverter = new ASCIIEncoding();

        public static RijndaelManaged getAESCBCCipher(byte[] keyBytes, byte[] IVBytes, PaddingMode padding)
        {
            RijndaelManaged cipher = new RijndaelManaged();
            cipher.KeySize = 128;
            cipher.BlockSize = 128;
            cipher.Mode = CipherMode.CBC;
            cipher.Padding = padding;
            cipher.IV = IVBytes;
            cipher.Key = keyBytes;
            return cipher;
        }

        public static RijndaelManaged getAESECBCipher(byte[] keyBytes, PaddingMode padding)
        {
            RijndaelManaged cipher = new RijndaelManaged();
            cipher.KeySize = 128;
            cipher.BlockSize = 128;
            cipher.Mode = CipherMode.ECB;
            cipher.Padding = padding;
            cipher.Key = keyBytes;
            return cipher;
        }

        public static byte[] encrypt(RijndaelManaged cipher, byte[] toEncrypt)
        {
            //Get an encryptor.
            ICryptoTransform encryptor = cipher.CreateEncryptor();
            //Encrypt the data.
            MemoryStream msEncrypt = new MemoryStream();
            CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
            //Write all data to the crypto stream and flush it.
            csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
            csEncrypt.FlushFinalBlock();

            //Get encrypted array of bytes.
            return msEncrypt.ToArray();
        }

        public static byte[] decrypt(RijndaelManaged cipher, byte[] encrypted)
        {
            //Get an encryptor.
            ICryptoTransform decryptor = cipher.CreateDecryptor();
            //Now decrypt the previously encrypted message using the decryptor
            // obtained in the above step.
            MemoryStream msDecrypt = new MemoryStream(encrypted);
            CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
            byte[] fromEncrypt = new byte[encrypted.Length];
            //Read the data out of the crypto stream.
            //csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
            csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
            return fromEncrypt;
        }

        public static byte[] encryptCBC(byte[] keyBytes, byte[] ivBytes, PaddingMode padding, byte[] messageBytes)
        {
            RijndaelManaged cipher = getAESCBCCipher(keyBytes, ivBytes, padding);
            return encrypt(cipher, messageBytes);
        }

        public static byte[] decryptCBC(byte[] keyBytes, byte[] ivBytes, PaddingMode padding, byte[] encryptedMessageBytes)
        {
            RijndaelManaged decipher = getAESCBCCipher(keyBytes, ivBytes, padding);
            return decrypt(decipher, encryptedMessageBytes);
        }

        public static byte[] encryptECB(byte[] keyBytes, PaddingMode padding, byte[] messageBytes)
        {
            RijndaelManaged cipher = getAESECBCipher(keyBytes, padding);
            return encrypt(cipher, messageBytes);
        }

        public static byte[] decryptECB(byte[] keyBytes, PaddingMode padding, byte[] encryptedMessageBytes)
        {
            RijndaelManaged decipher = getAESECBCipher(keyBytes, padding);
            return decrypt(decipher, encryptedMessageBytes);
        }

        public static string encodeText(string text)
        {
            return HttpUtility.UrlEncode(System.Convert.ToBase64String(textConverter.GetBytes(text)));
        }

        public static string decodeText(string text)
        {
            string s = "";
            try { s = textConverter.GetString(System.Convert.FromBase64String(HttpUtility.UrlDecode(text))); }
            catch (Exception e) { }//consider a good error handling
            return s;
        }

        public static string parseValue(string valueName, string token) 
        {
            string result = null;
            string[] values = token.Split(';');
            foreach (string value in values)
            {
                string[] pair = value.Split('=');
                if (valueName.Equals(pair[0]))
                    result = pair[1];
            }
            return result;
        }
    }
}
